package com.tencent.wxcloudrun.config;

import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
@Slf4j
public class RedissonLockService {

    @Resource
    private RedissonClient redissonClient;

    /**
     * 尝试在指定时间内获取分布式锁
     *
     * @param key      分布式锁的键名
     * @param waitTime 线程等待获取锁的最大时间（单位：毫秒）
     * @param expire   锁的有效期（单位：毫秒）
     * @return 是否成功获取到了锁
     */
    public boolean lock(String key, int waitTime, long expire) {
        RLock lock = redissonClient.getLock(key);
        log.info("尝试使用此key加锁: {}", key);
        try {
            // 阻塞形式: 这个方法尝试获取锁，如果锁可用，则立即获取锁并返回 true；如果锁不可用，则等待指定的时间，如果在等待时间内锁可用，则获取锁并返回 true；如果等待时间结束锁仍不可用，则返回 false。此外，获取锁后，锁的持有时间是 expire。
//            boolean isLocked = lock.tryLock(waitTime, expire, TimeUnit.MILLISECONDS);
            // 非阻塞形式: 这个方法尝试获取锁，如果锁可用，则立即获取锁并返回 true；如果锁不可用，则立即返回 false。
            boolean isLocked = lock.tryLock(); //
            if (isLocked) {
                log.info("成功使用此key加锁: {}", key);
            } else {
                log.warn("使用此key加锁失败: {}", key);
            }
            return isLocked;
        } catch (Exception e) {
            Thread.currentThread().interrupt(); // 重新设置中断状态
            log.info("使用此key加锁出现异常: {}  {}", key, e.getMessage());
        }
        return false;
    }

    /**
     * 释放分布式锁
     */
    public void unlock(String key) {
        RLock lock = redissonClient.getLock(key);
        if (lock.isLocked() && lock.isHeldByCurrentThread()) {
            lock.unlock();
            log.info("成功将此key的锁释放: {}", key);
        } else {
            if (!lock.isLocked()) {
                log.warn("此key的锁已经被释放: {}", key);
            } else {
                log.warn("此key的锁未被当前线程持有: {}", key);
            }
        }
    }
}